#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from 'zod';
import { zodToJsonSchema } from 'zod-to-json-schema';
import fetch, { Request, Response } from 'node-fetch';

// 导入各模块操作
import * as repository from './operations/repository.js';
import * as members from './operations/members.js';
import * as commit from './operations/commit.js';
import * as file from './operations/file.js';
import * as user from './operations/user.js';
import * as webhook from './operations/webhook.js';
import * as project from './operations/project.js';
import * as branch from './operations/branch.js';

// 导入错误处理
import {
  CodeArtsRepoError,
  CodeArtsRepoValidationError,
  CodeArtsRepoResourceNotFoundError,
  CodeArtsRepoAuthenticationError,
  CodeArtsRepoPermissionError,
  CodeArtsRepoRateLimitError,
  CodeArtsRepoConflictError,
  isCodeArtsRepoError,
} from './common/errors.js';
import { VERSION } from "./common/version.js";

// 如果全局作用域中没有fetch，则添加
if (!globalThis.fetch) {
  globalThis.fetch = fetch as unknown as typeof global.fetch;
}

const server = new Server(
  {
    name: "codeartsrepo-mcp-server",
    version: VERSION,
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// 格式化错误信息
function formatCodeArtsRepoError(error: CodeArtsRepoError): string {
  let message = `CodeArtsRepo API 错误: ${error.message}`;
  
  if (error instanceof CodeArtsRepoValidationError) {
    message = `验证错误: ${error.message}`;
    if (error.response) {
      message += `\n详情: ${JSON.stringify(error.response)}`;
    }
  } else if (error instanceof CodeArtsRepoResourceNotFoundError) {
    message = `未找到: ${error.message}`;
  } else if (error instanceof CodeArtsRepoAuthenticationError) {
    message = `认证失败: ${error.message}`;
  } else if (error instanceof CodeArtsRepoPermissionError) {
    message = `权限被拒绝: ${error.message}`;
  } else if (error instanceof CodeArtsRepoRateLimitError) {
    message = `超出频率限制: ${error.message}\n重置时间: ${error.resetAt.toISOString()}`;
  } else if (error instanceof CodeArtsRepoConflictError) {
    message = `冲突: ${error.message}`;
  }

  return message;
}

// 注册工具
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      // 仓库相关
      {
        name: "list_user_repositories",
        description: "获取用户的所有仓库信息",
        inputSchema: zodToJsonSchema(repository.ListUserAllRepositoriesSchema),
      },
      {
        name: "create_project_and_repositories",
        description: "创建项目和仓库",
        inputSchema: zodToJsonSchema(repository.CreateProjectAndRepositoriesSchema),
      },
      {
        name: "create_project_and_fork_repositories",
        description: "创建项目并fork仓库",
        inputSchema: zodToJsonSchema(repository.CreateProjectAndForkRepositoriesSchema),
      },
      {
        name: "show_project_repositories",
        description: "查询项目下的所有仓库",
        inputSchema: zodToJsonSchema(repository.ShowAllRepositoryByTwoProjectIdSchema),
      },
      {
        name: "associate_issues",
        description: "分支关联工作项",
        inputSchema: zodToJsonSchema(repository.AssociateIssuesSchema),
      },
      
      // 仓库成员相关
      {
        name: "list_repo_members",
        description: "获取仓库所有成员记录",
        inputSchema: zodToJsonSchema(members.ListRepoMembersSchema),
      },
      {
        name: "add_repo_members",
        description: "添加仓库成员",
        inputSchema: zodToJsonSchema(members.AddRepoMembersSchema),
      },
      {
        name: "set_repo_role",
        description: "设置成员在仓库中的角色",
        inputSchema: zodToJsonSchema(members.SetRepoRoleSchema),
      },
      {
        name: "delete_repo_member",
        description: "删除仓库成员",
        inputSchema: zodToJsonSchema(members.DeleteRepoMemberSchema),
      },
      
      // 提交相关
      {
        name: "list_commits",
        description: "查询某个仓库的提交信息",
        inputSchema: zodToJsonSchema(commit.ListCommitsSchema),
      },
      {
        name: "create_commit",
        description: "创建提交",
        inputSchema: zodToJsonSchema(commit.CreateCommitSchema),
      },
      {
        name: "show_single_commit",
        description: "查询某个仓库的特定提交信息",
        inputSchema: zodToJsonSchema(commit.ShowSingleCommitSchema),
      },
      {
        name: "show_diff_commit",
        description: "查询某个仓库的提交差异信息",
        inputSchema: zodToJsonSchema(commit.ShowDiffCommitSchema),
      },
      
      // 文件相关
      {
        name: "list_files",
        description: "查询某个仓库的文件信息",
        inputSchema: zodToJsonSchema(file.ListFilesByQuerySchema),
      },
      
      // 用户相关
      {
        name: "validate_https_info",
        description: "https账号密码校验",
        inputSchema: zodToJsonSchema(user.ValidateHttpsInfoV2Schema),
      },
      
      // Webhook相关
      {
        name: "list_hooks",
        description: "查询指定仓库的webhook",
        inputSchema: zodToJsonSchema(webhook.ListHooksSchema),
      },
      {
        name: "add_hooks",
        description: "为指定仓库添加hook",
        inputSchema: zodToJsonSchema(webhook.AddHooksSchema),
      },
      {
        name: "delete_hooks",
        description: "删除指定仓库的hook",
        inputSchema: zodToJsonSchema(webhook.DeleteHooksSchema),
      },
      
      // 项目相关
      {
        name: "list_product_templates",
        description: "获取一个项目下可以设置为公开状态的仓库列表",
        inputSchema: zodToJsonSchema(project.ListProductTwoTemplatesSchema),
      },
      {
        name: "show_repository_name_exist",
        description: "校验指定项目下的仓库名",
        inputSchema: zodToJsonSchema(project.ShowRepositoryNameExistSchema),
      },
      
      // 分支相关
      {
        name: "create_branch",
        description: "创建分支",
        inputSchema: zodToJsonSchema(branch.CreateNewBranchSchema),
      },
    ],
  };
});

// 处理工具调用
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  try {
    if (!request.params.arguments) {
      throw new Error("参数必填");
    }

    switch (request.params.name) {
      // 仓库相关
      case "list_user_repositories": {
        const args = repository.ListUserAllRepositoriesSchema.parse(request.params.arguments);
        const repos = await repository.listUserAllRepositories(
          args.user_id,
          args.page,
          args.per_page,
          args.search
        );
        return {
          content: [{ type: "text", text: JSON.stringify(repos, null, 2) }],
        };
      }

      case "create_project_and_repositories": {
        const args = repository.CreateProjectAndRepositoriesSchema.parse(request.params.arguments);
        const result = await repository.createProjectAndRepositories(args);
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      }

      case "create_project_and_fork_repositories": {
        const args = repository.CreateProjectAndForkRepositoriesSchema.parse(request.params.arguments);
        const result = await repository.createProjectAndForkRepositories(args);
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      }

      case "show_project_repositories": {
        const args = repository.ShowAllRepositoryByTwoProjectIdSchema.parse(request.params.arguments);
        const repos = await repository.showAllRepositoryByTwoProjectId(
          args.project_id,
          args.page,
          args.per_page,
          args.search
        );
        return {
          content: [{ type: "text", text: JSON.stringify(repos, null, 2) }],
        };
      }

      case "associate_issues": {
        const args = repository.AssociateIssuesSchema.parse(request.params.arguments);
        const result = await repository.associateIssues(
          args.project_id,
          args.branch_id,
          args.issues
        );
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      }

      // 仓库成员相关
      case "list_repo_members": {
        const args = members.ListRepoMembersSchema.parse(request.params.arguments);
        const memberList = await members.listRepoMembers(
          args.project_id,
          args.repo_id,
          args.search,
          args.page,
          args.per_page
        );
        return {
          content: [{ type: "text", text: JSON.stringify(memberList, null, 2) }],
        };
      }

      case "add_repo_members": {
        const args = members.AddRepoMembersSchema.parse(request.params.arguments);
        const result = await members.addRepoMembers(
          args.project_id,
          args.repo_id,
          args.user_ids,
          args.access_level
        );
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      }

      case "set_repo_role": {
        const args = members.SetRepoRoleSchema.parse(request.params.arguments);
        const result = await members.setRepoRole(
          args.project_id,
          args.repo_id,
          args.user_id,
          args.access_level
        );
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      }

      case "delete_repo_member": {
        const args = members.DeleteRepoMemberSchema.parse(request.params.arguments);
        const result = await members.deleteRepoMember(
          args.project_id,
          args.repo_id,
          args.user_id
        );
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      }

      // 提交相关
      case "list_commits": {
        const args = commit.ListCommitsSchema.parse(request.params.arguments);
        const commits = await commit.listCommits(
          args.project_id,
          args.repo_id,
          {
            path: args.path,
            branch: args.branch,
            page: args.page,
            perPage: args.per_page
          }
        );
        return {
          content: [{ type: "text", text: JSON.stringify(commits, null, 2) }],
        };
      }

      case "create_commit": {
        const args = commit.CreateCommitSchema.parse(request.params.arguments);
        const result = await commit.createCommit(
          args.project_id,
          args.repo_id,
          args.branch,
          args.commit_message,
          args.actions,
          args.force
        );
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      }

      case "show_single_commit": {
        const args = commit.ShowSingleCommitSchema.parse(request.params.arguments);
        const commitInfo = await commit.getSingleCommit(
          args.project_id,
          args.repo_id,
          args.commit_id
        );
        return {
          content: [{ type: "text", text: JSON.stringify(commitInfo, null, 2) }],
        };
      }

      case "show_diff_commit": {
        const args = commit.ShowDiffCommitSchema.parse(request.params.arguments);
        const diff = await commit.showDiffCommit(
          args.project_id,
          args.repo_id,
          args.commit_id
        );
        return {
          content: [{ type: "text", text: JSON.stringify(diff, null, 2) }],
        };
      }

      // 文件相关
      case "list_files": {
        const args = file.ListFilesByQuerySchema.parse(request.params.arguments);
        const files = await file.listFilesByQuery(
          args.project_id,
          args.repo_id,
          args.path,
          args.ref
        );
        return {
          content: [{ type: "text", text: JSON.stringify(files, null, 2) }],
        };
      }

      // 用户相关
      case "validate_https_info": {
        const args = user.ValidateHttpsInfoV2Schema.parse(request.params.arguments);
        const result = await user.validateHttpsInfoV2(
          args.username,
          args.password
        );
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      }

      // Webhook相关
      case "list_hooks": {
        const args = webhook.ListHooksSchema.parse(request.params.arguments);
        const hooks = await webhook.listHooks(
          args.project_id,
          args.repo_id
        );
        return {
          content: [{ type: "text", text: JSON.stringify(hooks, null, 2) }],
        };
      }

      case "add_hooks": {
        const args = webhook.AddHooksSchema.parse(request.params.arguments);
        const result = await webhook.addHooks(
          args.project_id,
          args.repo_id,
          {
            url: args.url,
            events: args.events,
            enabled: args.enabled,
            token: args.token,
            ssl_verification: args.ssl_verification
          }
        );
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      }

      case "delete_hooks": {
        const args = webhook.DeleteHooksSchema.parse(request.params.arguments);
        const result = await webhook.deleteHooks(
          args.project_id,
          args.repo_id,
          args.hook_id
        );
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      }

      // 项目相关
      case "list_product_templates": {
        const args = project.ListProductTwoTemplatesSchema.parse(request.params.arguments);
        const templates = await project.listProductTwoTemplates(
          args.project_id
        );
        return {
          content: [{ type: "text", text: JSON.stringify(templates, null, 2) }],
        };
      }

      case "show_repository_name_exist": {
        const args = project.ShowRepositoryNameExistSchema.parse(request.params.arguments);
        const result = await project.showRepositoryNameExist(
          args.project_id,
          args.repo_name
        );
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      }
      
      // 分支相关
      case "create_branch": {
        const args = branch.CreateNewBranchSchema.parse(request.params.arguments);
        const result = await branch.createNewBranch(
          args.project_id,
          args.repo_id,
          args.branch,
          args.ref
        );
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      }

      default:
        throw new Error(`未知的工具: ${request.params.name}`);
    }
  } catch (error) {
    console.error("Error handling request:", error);
    
    if (isCodeArtsRepoError(error)) {
      return {
        error: formatCodeArtsRepoError(error),
      };
    }
    
    return {
      error: `Error: ${error}`,
    };
  }
});

// 启动服务器
const transport = new StdioServerTransport();
server.listen(transport);

console.log(`CodeArtsRepo MCP Server v${VERSION} 已启动`); 